package by.ostrovsky.webhousingsystem.junit.hardcode;

import java.util.LinkedList;
import java.util.List;

import junit.framework.TestCase;

import org.apache.log4j.Logger;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import by.ostrovsky.webhousingsystem.dao.DAOFactory;
import by.ostrovsky.webhousingsystem.dao.implementation.idao.IOperateDAO;
import by.ostrovsky.webhousingsystem.dao.implementation.idao.IReadDAO;
import by.ostrovsky.webhousingsystem.hibernate.entity.Employee;
import by.ostrovsky.webhousingsystem.hibernate.entity.TaskGroup;
import by.ostrovsky.webhousingsystem.hibernate.entity.UserRequest;
import by.ostrovsky.webhousingsystem.hibernate.entity.WorkPlan;

public class AcceptRequestTest extends TestCase {
	private DAOFactory factory = null;
	private static Logger logger = Logger.getLogger(AcceptRequestTest.class);
	private IReadDAO<UserRequest> requestreadalldao = null;
	private IReadDAO<Employee> employeereadalldao = null;
	private IReadDAO<TaskGroup> taskgroupreadalldao = null;
	private IReadDAO<WorkPlan> workplanreadalldao = null;
	private IOperateDAO<List<UserRequest>, Boolean> requestcuddao = null;
	private IOperateDAO<List<WorkPlan>, Boolean> workplancuddao = null;
	private IOperateDAO<List<Employee>, Boolean> employeecuddao = null;
	private IOperateDAO<List<TaskGroup>, Boolean> taskgroupcuddao = null;

	@Before
	public void setUp() throws Exception {
		factory = DAOFactory.getDAOFactory(DAOFactory.MySQL);
		requestreadalldao = factory.getReadHousingRequestDAO();
		workplancuddao = factory.getWorkPlanDAO();
		taskgroupreadalldao = factory.getReadTaskGroupDAO();
		taskgroupcuddao = factory.getTaskGroupDAO();
		employeereadalldao = factory.getReadEmployeDAO();
		employeecuddao = factory.getEmployeDAO();
	}

	@After
	public void tearDown() throws Exception {
	}

	public static int getRandInRange(int min, int max) {
		return (int) (Math.random() * (max - min) + min);
	}

	@Test
	public void test() {
		try {
			// step 1 -------------------------------------------------
			// changing Employee table info
			// creating new TaskGroup table row
			// getting requests
			List<UserRequest> urlist = appointEmployesToTheTaskgroup();
			// step 2 -------------------------------------------------
			// creating new WorkPlan table row
			setNewWork(urlist);
			try {
				// step 3 ---------------------------------------------
				// deleting accepted requests
				requestcuddao.delete(urlist);
			} catch (Exception e) {
				logger.error(e);
				fail();
			}
		} catch (Exception e) {
			logger.error(e);
			fail();
		}

	}

	public void setNewWork(List<UserRequest> urlist) {
		try {
			List<WorkPlan> worklist = new LinkedList<WorkPlan>();
			List<WorkPlan> worktmplist = new LinkedList<WorkPlan>();
			List<TaskGroup> tglist = new LinkedList<TaskGroup>();

			try {
				tglist.addAll(tryToReadTaskGroup());
				worklist.addAll(tryToReadWorkPlan());
			} catch (NullPointerException e) {
				logger.error(e);
			}

			for (int i = 0; i < urlist.size(); i++) {
				UserRequest ur = new UserRequest();
				TaskGroup tg = new TaskGroup();
				WorkPlan wp = new WorkPlan();
				wp.setDeadline(urlist.get(i).getDeadline());
				wp.setDone(false);
				if(worklist.size() != 0)
					wp.setId((long) (i + worklist.size()));
				else
					wp.setId((long) i+1);
				ur.setId(urlist.get(i).getId());
				wp.setRequestedWork(ur);

				for (int j = 0; j < tglist.size(); j++) {
					boolean match = tglist.get(j).getAppointment()
							.equals(urlist.get(i).getWork());
					if (match) {
						tg = tglist.get(j);
						tglist.remove(j);
						break;
					}
				}
				wp.setTaskGroup(tg);
				worktmplist.add(wp);
			}

			try {
				workplancuddao.create(worktmplist);
			} catch (Exception e) {
				logger.error(e);
			}

		} catch (Exception e) {
			logger.error(e);
		}
	}

	public List<UserRequest> appointEmployesToTheTaskgroup() {
		try {
			List<UserRequest> urlist = new LinkedList<UserRequest>();
			List<UserRequest> urtmplist = new LinkedList<UserRequest>();
			List<TaskGroup> tglist = new LinkedList<TaskGroup>();
			List<TaskGroup> tgtmplist = new LinkedList<TaskGroup>();
			List<Employee> elist = new LinkedList<Employee>();
			List<Employee> etmplist = new LinkedList<Employee>();

			try {
				tglist.addAll(tryToReadTaskGroup());
				urlist.addAll(tryToReadRequest());
				elist.addAll(tryToReadEmployee());
			} catch (NullPointerException e) {
				logger.error(e);
			}

			int tmp;
			for (int i = 0; i < 20; i++) {
				tmp = getRandInRange(0, urlist.size());
				urtmplist.add(urlist.get(tmp));
				urlist.remove(tmp);
			}
			urlist = null;

			Employee emp;
			
			for (int i = 0; i < urtmplist.size(); i++) {

				List<Employee> tmpbrigade = new LinkedList<Employee>();
				TaskGroup tg = new TaskGroup();
				
				if (tglist.size() != 0)
					tg.setId(tglist.get(tglist.size() - 1).getId() + 1);
				else
					tg.setId((long) i);
			
				for (int j = 0; j < elist.size(); j++) {

					emp = elist.get(j);
					boolean match = urtmplist.get(i).getWork()
							.equals(emp.getSpeciality());
					boolean ismaster = emp.getIsMaster();

					if (!ismaster && match && tmpbrigade.size() < 3) {
						elist.get(j).setIsBusy(true);
						elist.get(j).setFreeAt(urtmplist.get(i).getDeadline());
						elist.get(j).setTaskGroup(tg);
						etmplist.add(elist.get(j));
					}

					if (tmpbrigade.size() == 2)
						if (match && ismaster) {
							elist.get(j).setIsBusy(true);
							elist.get(j).setFreeAt(
									urtmplist.get(i).getDeadline());
							elist.get(j).setTaskGroup(tg);
							etmplist.add(elist.get(j));
							break;
						}
				}
				tg.setIsBusy(true);
				tg.setFreeAt(urtmplist.get(i).getDeadline());
				tg.setAppointment(urtmplist.get(i).getWork());
				tgtmplist.add(tg);
			}

			try {
				taskgroupcuddao.create(tgtmplist);
				employeecuddao.update(etmplist);
			} catch (Exception e) {
				logger.error(e);
			}

			return urtmplist;
		} catch (Exception e) {
			logger.error(e);
			return null;
		}
	}

	public List<WorkPlan> tryToReadWorkPlan() {
		List<WorkPlan> list = new LinkedList<WorkPlan>();
		try {
			list.addAll(workplanreadalldao.readAll());
			return list;
		} catch (Exception e) {
			logger.info(e);
		}
		return list;
	}

	public List<TaskGroup> tryToReadTaskGroup() {
		List<TaskGroup> list = new LinkedList<TaskGroup>();
		try {
			list.addAll(taskgroupreadalldao.readAll());
			return list;
		} catch (Exception e) {
			logger.info(e);
		}
		return list;
	}

	public List<Employee> tryToReadEmployee() {
		List<Employee> list = new LinkedList<Employee>();
		try {
			list.addAll(employeereadalldao.readAll());
			return list;
		} catch (Exception e) {
			logger.info(e);
		}
		return list;
	}

	public List<UserRequest> tryToReadRequest() {
		List<UserRequest> list = new LinkedList<UserRequest>();
		try {
			list.addAll(requestreadalldao.readAll());
			return list;
		} catch (Exception e) {
			logger.info(e);
		}
		return list;
	}
}
